//  Filename:  stdcell_lib.v
//  Function:  define all of stdlib modules for common use
//======================================================================
// Cell List:
//   0-0.  clk inv
//   0-1.  clk buf
//   0-2.  clk nand2
//   0-3.  clk or2
//   0-4.  clk 2mux1 nor
//   0-5.  clk 4mux1 nor
//   0-6.  clk icg
//   0-7.  clk icg_n
//   0-8.  clk always icg
//   0-9.  clk 3mux1 nor
//   0-10. clk or3
//   0-11. clk or4
//   0-12. clk xor2
//   0-13. clk mux2(with out SE)
//
//   1-0.  buf
//   1-1.  strong buf
//   1-2.  nand2
//   1-3.  and2
//   1-4.  2mux1 
//   1-5.  4mux1 
//   1-6.  master-slave latch
//   1-7.  d-latch
//   1-8.  dff init1
//   1-9.  dff init0
//
//   2-0.  TRNG dly chain 
//   2-1.  TRNG dly buf
//   2-2.  delay chain 4mux1
//   2-3.  delay chain 2mux1

module stdlib_clk_inv(
     input  clk_in,
     output clk_inv_out
);

assign clk_inv_out = ~clk_in;

endmodule

module stdlib_clk_buf(
     input  clk_in,
     output clk_out
);

assign clk_out = clk_in;

endmodule

module stdlib_clk_nand(
     input  clk0,
     input  clk1,
     output clk_out
);

assign clk_out = ~(clk0 & clk1);

endmodule

module stdlib_clk_or(
     input       clk0,
     input       clk1,
     output      clk_out 
);
wire   clk0_inv, clk1_inv;
assign clk_out = (clk0 | clk1);
endmodule

module stdlib_clk_2mux1_nor(
        input       SE  ,
        input       rstn,
        input       test_mode,
        input       test_resetn,
        input       clk0,
        input       clk1,
        input       sel ,
        output      out_clk
);

assign out_clk = sel ? clk1 : clk0;

endmodule

module stdlib_clk_4mux1_nor(
        input       SE  ,
        input       test_mode,
        input       test_resetn,
        input       rstn,
        input       clk0,
        input       clk1,
        input       clk2,
        input       clk3,
        input [1:0] sel ,
        output      out_clk
);
wire out_clk01;
wire out_clk23;

assign out_clk01 = sel[0] ? clk1 : clk0;
assign out_clk23 = sel[0] ? clk3 : clk2;
assign out_clk   = sel[1] ? out_clk23 : out_clk01;

endmodule

module stdlib_clk_icg(
    input  SE,
    input  clk_in,
    input  en,
    output out_clk
);

reg en_latch; // level sensitive latch
always @(clk_in or en or SE) begin
  if (!clk_in)
    en_latch <= en || SE;
end
assign out_clk = clk_in && en_latch;

endmodule

module stdlib_clk_icg_n(
    input  SE,
    input  clk_in,
    input  en,
    output out_clk
);

reg en_latch; // level sensitive latch
always @(clk_in or en or SE) begin
  if (clk_in)
    en_latch <= en || SE;
end
assign out_clk = clk_in | (~en_latch);

endmodule

module stdlib_clk_always_icg(
    input  SE,
    input  clk_in,
    input  en,
    output out_clk
);
reg en_latch; //level sensitive latch
always @(clk_in or en or SE) begin
  if (!clk_in)
    en_latch <= en | SE;
end
assign out_clk = clk_in & en_latch;
endmodule

module stdlib_clk_3mux1_nor(
        input       SE,
        input       test_mode,
        input       test_resetn,
        input       rstn,
        input       clk0,
        input       clk1,
        input       clk2,
        input [1:0] sel,
        output      out_clk
    );
wire out_clk01;

assign out_clk01 = sel[0] ? clk1 : clk0;
assign out_clk   = sel[1] ? clk2 : out_clk01;

endmodule

module stdlib_clk_or3(
     input       clk0,
     input       clk1,
     input       clk2,
     output      clk_out 
);
wire clk0_inv, clk1_inv, clk2_inv;
wire clk_01_invand, clk_012_invand;

assign  clk_out = (clk0 | clk1 | clk2);

endmodule

module stdlib_clk_or4(
     input       clk0,
     input       clk1,
     input       clk2,
     input       clk3,
     output      clk_out 
);
wire clk0_inv, clk1_inv, clk2_inv, clk3_inv;
wire clk_01_inv, clk_23_inv, clk_4invand;

assign  clk_out = (clk0 | clk1 | clk2 | clk3);

endmodule

module stdlib_clk_xor2
(
  input  clk0,
  input  clk1, 
  output out_clk
);

assign out_clk  = clk0 ^ clk1;

endmodule

module stdlib_clk_mux(
        input       clk0,
        input       clk1,
        input       sel ,
        output      out_clk
);

assign out_clk = sel ? clk1 : clk0;

endmodule

module stdlib_clk_and2
(
     input       clk0,
     input       clk1,
     output      clk_out 
);

assign  clk_out = clk0 & clk1;

endmodule

module stdlib_buf(
     input din,
     output z_out
);

assign  z_out = din;

endmodule

module stdlib_strong_buf(
     input din,
     output z_out
);

assign  z_out = din;

endmodule

module stdlib_nand2(
     input a1,
     input a2,
     output zn_out
);

assign  zn_out = ~(a1 & a2);

endmodule

module stdlib_and2(
     input a1,
     input a2,
     output z_out
);

assign  z_out = a1 & a2;

endmodule

module stdlib_mux2(
  input   I0,
  input   I1,
  input   sel,
  output  z_out
);

assign z_out = sel ? I1 : I0;

endmodule

module stdlib_mux4(
     input       I0,
     input       I1,
     input       I2,
     input       I3,
     input [1:0] sel,
     output      z_out
);

assign  z_out = (sel==2'b00) ? I0 :
                (sel==2'b01) ? I1 :
                (sel==2'b10) ? I2 : I3;

endmodule

module stdlib_ms_latch(
     input  din,
     input  en,
     output q_out
);

reg   q_out_pre;
reg   q_out_tmp;

always @(din or en) begin
  if(!en) begin
    q_out_pre <= din;
  end
end
always @(q_out_pre or en) begin
  if(en) begin
    q_out_tmp <= q_out_pre;
  end
end
assign  q_out = q_out_tmp;

endmodule

module stdlib_dlatch(
     input  D
    ,input  EN
    ,output Q
);

reg Q_tmp;
always @(D or EN) begin
  if(EN)  Q_tmp <= D;
end
assign  Q = Q_tmp;

endmodule

module stdlib_dff_init1
(
  input  d,
  input  clk,
  input  rstn,
  input  SE,
  output q_out
);

reg  q_tmp;
always @(posedge clk or negedge rstn) begin
  if(!rstn) 
    q_tmp <= 1'b1;
  else
    q_tmp <= d;
end
assign  q_out = q_tmp;

endmodule

module stdlib_dff_init0(
  input d,
  input clk,
  input rstn,
  input SE,
  output q_out
);

reg  q_tmp;
always @(posedge clk or negedge rstn) begin
  if(!rstn) 
    q_tmp <= 1'b0;
  else
    q_tmp <= d;
end
assign  q_out = q_tmp;

endmodule

module stdlib_trng_dly(
     output    dly_out 
    ,input     dly_in 
);

reg  dly_out_sim;
always@(*) begin
  dly_out_sim = #0.150 dly_in;
end
assign dly_out = dly_out_sim;

endmodule

module stdlib_trng_buf(
     input din,
     output z_out
);

assign  z_out = din;

endmodule

module stdlib_dly_chain_mux4
(
   input         I0,
   input         I1,
   input         I2,
   input         I3,
   input  [1:0]  sel,
   output        Z
);

assign  Z = (sel==0) ? I0 :
            (sel==1) ? I1 :
            (sel==2) ? I2 : I3;

endmodule

module stdlib_dly_chain_mux2
(
   input         I0,
   input         I1,
   input         sel, 
   output        Z
);

assign  Z = (sel==0) ? I0 : I1;

endmodule

module stdlib_dly200p_cell(
     output    dly_out, //200ps
     input     dly_in 
);
    reg  dly_out_sim;
    always@(*) begin
      dly_out_sim = #0.200 dly_in;
    end
    assign dly_out = dly_out_sim;
endmodule

module stdlib_rstn_sync(
   input      rstn_in,
   input      sync_clock,
   input      test_mode,
   input      test_resetn,
   output     rstn_out,
);

wire  rstn_func;
reg   rstn_sync_1d_r, rstn_sync_2d_r;

always@(posedge sync_clock or negedge rstn_in) begin
  if(!rstn_in) begin
    rstn_sync_1d_r <= 1'b0;
    rstn_sync_2d_r <= 1'b0;
  end else begin
    rstn_sync_1d_r <= 1'b1;
    rstn_sync_2d_r <= rstn_sync_1d_r;
  end
end 
assign  rstn_func = rstn_sync_2d_r;
stdlib_test_reset_mux u0_reset_testmux
(
    .test_mode  (test_mode),
    .rstn_in    (rstn_func),
    .test_resetn (test_resetn),
    .rstn_out   (rstn_out)
);

endmodule

module stdlib_rstn_sync_3dff(
   input      rstn_in,
   input      sync_clock,
   input      test_mode,
   input      test_resetn,
   output     rstn_out 
);
wire  rstn_func;
reg   rstn_sync_1d_r, rstn_sync_2d_r, rstn_sync_3d_r;

always@(posedge sync_clock or negedge rstn_in) begin
  if(!rstn_in) begin
    rstn_sync_1d_r <= 1'b0;
    rstn_sync_2d_r <= 1'b0;
    rstn_sync_3d_r <= 1'b0;
  end else begin
    rstn_sync_1d_r <= 1'b1;
    rstn_sync_2d_r <= rstn_sync_1d_r;
    rstn_sync_3d_r <= rstn_sync_2d_r;
  end
end 
assign  rstn_func = rstn_sync_3d_r;

stdlib_test_reset_mux u0_reset_testmux
(
    .test_mode  (test_mode),
    .rstn_in    (rstn_func),
    .test_resetn (test_resetn),
    .rstn_out   (rstn_out)
);

endmodule

module stdlib_sync_init0(
     input  clk,
     input  SE,
     input  data_in,
     input  rstn,
     output data_out 
);
wire   data_out_d0;

stdlib_dff_init0 u0_sync_ph0 ( .d(data_in),     .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out_d0));
stdlib_dff_init0 u0_sync_ph1 ( .d(data_out_d0), .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out));

endmodule

module stdlib_sync_init0_3dff(
     input  clk,
     input  SE,
     input  data_in,
     input  rstn,
     output data_out
);

wire   data_out_d0, data_out_d1;
stdlib_dff_init0 u0_sync_ph0 ( .d(data_in),     .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out_d0));
stdlib_dff_init0 u0_sync_ph1 ( .d(data_out_d0), .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out_d1));
stdlib_dff_init0 u0_sync_ph2 ( .d(data_out_d1), .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out));

endmodule

module stdlib_sync_init1(    
     input  clk,
     input  SE,
     input  data_in,
     input  rstn,
     output data_out 
);

wire   data_out_d0;
stdlib_dff_init1 u0_sync_ph0 ( .d(data_in),     .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out_d0));
stdlib_dff_init1 u0_sync_ph1 ( .d(data_out_d0), .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out));

endmodule

module stdlib_sync_init1_3dff(    
     input  clk,
     input  SE,
     input  data_in,
     input  rstn,
     output data_out 
);

wire   data_out_d0, data_out_d1;

stdlib_dff_init1 u0_sync_ph0 ( .d(data_in),     .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out_d0));
stdlib_dff_init1 u0_sync_ph1 ( .d(data_out_d0), .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out_d1));
stdlib_dff_init1 u0_sync_ph2 ( .d(data_out_d1), .clk(clk), .SE(SE), .rstn(rstn), .q_out(data_out));

endmodule

module stdlib_mulbit_sync #(parameter  BITWID=2, parameter DEFLT_VAL=0)
(
  input                clk_d,
  input                rst_d_n,
  input  [BITWID-1:0]  data_s,
  output [BITWID-1:0]  data_d
);
wire                rstn_clkd;
reg   [BITWID-1:0]  data_s_1d_r, data_s_2d_r, data_s_3d_r;
reg   [BITWID-1:0]  data_d_tmp_r;

assign   rstn_clkd = rst_d_n;
assign   data_d =  (BITWID==1) ? data_s_2d_r : data_d_tmp_r;
always @(posedge clk_d or negedge rstn_clkd) begin
  if(!rstn_clkd) begin
    data_s_1d_r <= DEFLT_VAL;
    data_s_2d_r <= DEFLT_VAL;
    data_s_3d_r <= DEFLT_VAL;
  end else begin
    data_s_1d_r <= data_s;
    data_s_2d_r <= data_s_1d_r;
    data_s_3d_r <= data_s_2d_r;
  end
end
always @(posedge clk_d or negedge rstn_clkd) begin
  if(!rstn_clkd)
    data_d_tmp_r <= DEFLT_VAL;
  else if(data_s_2d_r == data_s_3d_r)
    data_d_tmp_r <= data_s_3d_r;
end

endmodule

module stdlib_mulbit_sync_3dff  #(parameter  BITWID=2, parameter DEFLT_VAL=0)
(
  input                clk_d,
  input                rst_d_n,
  input  [BITWID-1:0]  data_s,
  output [BITWID-1:0]  data_d
);
wire                rstn_clkd;
reg   [BITWID-1:0]  data_s_1d_r, data_s_2d_r, data_s_3d_r, data_s_4d_r;
reg   [BITWID-1:0]  data_d_tmp_r;

assign   rstn_clkd = rst_d_n;
assign   data_d =  (BITWID==1) ? data_s_3d_r : data_d_tmp_r;
always @(posedge clk_d or negedge rstn_clkd) begin
  if(!rstn_clkd) begin
    data_s_1d_r <= DEFLT_VAL;
    data_s_2d_r <= DEFLT_VAL;
    data_s_3d_r <= DEFLT_VAL;
    data_s_4d_r <= DEFLT_VAL;
  end else begin
    data_s_1d_r <= data_s;
    data_s_2d_r <= data_s_1d_r;
    data_s_3d_r <= data_s_2d_r;
    data_s_4d_r <= data_s_3d_r;
  end
end
always @(posedge clk_d or negedge rstn_clkd) begin
  if(!rstn_clkd)
    data_d_tmp_r <= DEFLT_VAL;
  else if(data_s_3d_r == data_s_4d_r)
    data_d_tmp_r <= data_s_3d_r;
end

endmodule

module stdlib_onebit_sync #(parameter DEFLT_VAL=0)
(
  input                clk_d,
  input                rst_d_n,
  input                data_s,
  output               data_d
);
wire                rstn_clkd;
reg                 data_s_1d_r, data_s_2d_r;

assign   rstn_clkd = rst_d_n;
assign   data_d    = data_s_2d_r; 
always @(posedge clk_d or negedge rstn_clkd) begin
  if(!rstn_clkd) begin
    data_s_1d_r <= DEFLT_VAL;
    data_s_2d_r <= DEFLT_VAL;
  end else begin
    data_s_1d_r <= data_s;
    data_s_2d_r <= data_s_1d_r;
  end
end

endmodule

module stdlib_onebit_sync_3dff #(parameter DEFLT_VAL=0)
(
  input                clk_d,
  input                rst_d_n,
  input                data_s,
  output               data_d
);
wire                rstn_clkd;
reg                 data_s_1d_r, data_s_2d_r, data_s_3d_r;
assign   rstn_clkd = rst_d_n;
assign   data_d    = data_s_3d_r; 
always @(posedge clk_d or negedge rstn_clkd) begin
   if(!rstn_clkd) begin
      data_s_1d_r <= DEFLT_VAL;
      data_s_2d_r <= DEFLT_VAL;
      data_s_3d_r <= DEFLT_VAL;
   end else begin
      data_s_1d_r <= data_s;
      data_s_2d_r <= data_s_1d_r;
      data_s_3d_r <= data_s_2d_r;
   end
end
endmodule

module stdlib_clk_2mux1(
        input       SE,
        input       test_mode,
        input       test_resetn,
        input       rstn,
        input       clk0,
        input       clk1,
        input       sel ,
        output      out_clk
);
wire sel_buf;

stdlib_clk_buf   u0_sel_buf (.clk_in(sel), .clk_out(sel_buf));
stdlib_clkmux2_gfree u0_glitch_free_mux2(
      .rstn(rstn),
      .clk0(clk0),
      .clk1(clk1), 
      .SE(SE), 
      .test_mode(test_mode), 
      .test_resetn(test_resetn), 
      .sel(sel_buf),
      .clk_out(out_clk));

endmodule
//============================
module stdlib_clkmux2_gfree(
     input  clk0,
     input  clk1,
     input  SE,
     input  rstn,
     input  test_mode,
     input  test_resetn,
     input  sel,
     output clk_out
);
reg sel_clk0_d0;
reg sel_clk0_d1;
reg sel_clk0_d2;
reg sel_clk1_d0;
reg sel_clk1_d1;
reg sel_clk1_d2;
wire clk_out0,clk_out1;
wire rstn_clk0, rstn_clk1;

stdlib_rstn_sync  u0_rstn_sync (.rstn_in(rstn), .sync_clock(clk0), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk0));
stdlib_rstn_sync  u1_rstn_sync (.rstn_in(rstn), .sync_clock(clk1), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk1));

always@(posedge clk0 or negedge rstn_clk0) begin
  if(~rstn_clk0) begin
    sel_clk0_d0 <=1'b1; 
    sel_clk0_d1 <=1'b1; 
    sel_clk0_d2 <=1'b1; 
  end
  else begin
    sel_clk0_d0 <= ~(sel_clk1_d2|sel);
    sel_clk0_d1 <= sel_clk0_d0;
    sel_clk0_d2 <= sel_clk0_d1;
  end
end 
always@(posedge clk1 or negedge rstn_clk1) begin
  if(~rstn_clk1)begin
    sel_clk1_d0 <=1'b0; 
    sel_clk1_d1 <=1'b0; 
    sel_clk1_d2 <=1'b0; 
  end
  else begin
    sel_clk1_d0 <= ~(~sel|sel_clk0_d2);
    sel_clk1_d1 <= sel_clk1_d0;
    sel_clk1_d2 <= sel_clk1_d1;
  end
end 

stdlib_clk_icg u_ckmux_icg0(.SE(SE),.clk_in(clk0),.en(sel_clk0_d1),.out_clk(clk_out0));
stdlib_clk_icg u_ckmux_icg1(.SE(SE),.clk_in(clk1),.en(sel_clk1_d1),.out_clk(clk_out1));
stdlib_clk_or  u_ckmux_or (.clk0(clk_out0),.clk1(clk_out1),.clk_out(clk_out));
endmodule

module stdlib_clk_3mux1_or3(
  input           SE          ,
  input           test_mode   ,
  input           test_resetn ,
  input           clk0        ,
  input           clk1        ,
  input           clk2        ,
  input           rstn        ,
  input   [ 1:0]  sel         ,
  output          out_clk
);

stdlib_clkmux3_gfree u_stdlib_clkmux3_gfree(
  .clk0         (clk0   ),  
  .clk1         (clk1   ),
  .clk2         (clk2   ),
  .SE           (SE     ),
  .test_mode    (test_mode),
  .test_resetn  (test_resetn),
  .rstn         (rstn   ),
  .sel          (sel    ),
  .clk_out      (out_clk));

endmodule

module stdlib_clkmux3_gfree(
  input     wire            clk0        ,
  input     wire            clk1        ,
  input     wire            clk2        ,
  input     wire            SE          ,
  input     wire            test_mode   ,
  input     wire            test_resetn ,
  input     wire            rstn        ,
  input     wire    [ 1:0]  sel         ,
  output    wire            clk_out
);
// --------------------------
// Parameter Declaration
// --------------------------
    parameter ULDY = 0.1 ;
// --------------------------
// Wire Declaration
// --------------------------
    wire        clk_out0        ;
    wire        clk_out1        ;
    wire        clk_out2        ;
    wire        sel_clk0        ;
    wire        sel_clk1        ;
    wire        sel_clk2        ;
// --------------------------
// Reg Declaration
// --------------------------
    reg         sel_clk0_d0     ;
    reg         sel_clk0_d1     ;
    reg         sel_clk0_d2     ;
    reg         sel_clk1_d0     ;
    reg         sel_clk1_d1     ;
    reg         sel_clk1_d2     ;
    reg         sel_clk2_d0     ;
    reg         sel_clk2_d1     ;
    reg         sel_clk2_d2     ;
// --------------------------
//   Main Code Begin
// --------------------------
    wire rstn_clk0, rstn_clk1, rstn_clk2;
    stdlib_rstn_sync  u0_rstn_sync (.rstn_in(rstn), .sync_clock(clk0), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk0));
    stdlib_rstn_sync  u1_rstn_sync (.rstn_in(rstn), .sync_clock(clk1), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk1));
    stdlib_rstn_sync  u2_rstn_sync (.rstn_in(rstn), .sync_clock(clk2), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk2));
    //assign  rstn_clk0 = rstn;
    //assign  rstn_clk1 = rstn;
    //assign  rstn_clk2 = rstn;
    assign sel_clk0 =  (sel == 2'h0);
    assign sel_clk1 =  (sel == 2'h1);
    assign sel_clk2 =  sel[1];//(sel == 2'h2);
// ---------------------------
//  clk0
// ---------------------------
    always @(posedge clk0 or negedge rstn_clk0)begin
        if(~rstn_clk0)begin
            sel_clk0_d0 <= #ULDY 1'b0;
            sel_clk0_d1 <= #ULDY 1'b0;
            sel_clk0_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk0_d0 <= #ULDY sel_clk0 & (~sel_clk1_d2) & (~sel_clk2_d2);
            sel_clk0_d1 <= #ULDY sel_clk0_d0 ;
            sel_clk0_d2 <= #ULDY sel_clk0_d1 ;
        end
    end
// --------------------------
//  clk1
// --------------------------
    always @(posedge clk1 or negedge rstn_clk1)begin
        if(~rstn_clk1)begin
            sel_clk1_d0 <= #ULDY 1'b0;
            sel_clk1_d1 <= #ULDY 1'b0;
            sel_clk1_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk1_d0 <= #ULDY sel_clk1 & (~sel_clk0_d2) & (~sel_clk2_d2);
            sel_clk1_d1 <= #ULDY sel_clk1_d0 ;
            sel_clk1_d2 <= #ULDY sel_clk1_d1 ;
        end
    end
// --------------------------
//  clk2
// --------------------------
    always @(posedge clk2 or negedge rstn_clk2)begin
        if(~rstn_clk2)begin
            sel_clk2_d0 <= #ULDY 1'b0;
            sel_clk2_d1 <= #ULDY 1'b0;
            sel_clk2_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk2_d0 <= #ULDY sel_clk2 & (~sel_clk0_d2) & (~sel_clk1_d2);
            sel_clk2_d1 <= #ULDY sel_clk2_d0 ;
            sel_clk2_d2 <= #ULDY sel_clk2_d1 ;
        end
    end
    stdlib_clk_icg u_ckmux_icg0(.SE(SE),.clk_in(clk0),.en(sel_clk0_d1),.out_clk(clk_out0));
    stdlib_clk_icg u_ckmux_icg1(.SE(SE),.clk_in(clk1),.en(sel_clk1_d1),.out_clk(clk_out1));
    stdlib_clk_icg u_ckmux_icg2(.SE(SE),.clk_in(clk2),.en(sel_clk2_d1),.out_clk(clk_out2));
    stdlib_clk_or3 u_clk_or2 (.clk0(clk_out0), .clk1(clk_out1), .clk2(clk_out2), .clk_out(clk_out));
endmodule
//==============================================
//1-2: clock 3mux1 glitch free
module stdlib_clk_3mux1(
    input        SE,
    input        test_mode,
    input        test_resetn,
    input        rstn,
    input        clk0,
    input        clk1,
    input        clk2,
    input [1:0]  sel,
    output       out_clk
 );
wire [1:0]  sel_buf;
wire        out_clk01;
stdlib_clk_buf       u0_sel_buf (.clk_in(sel[0]), .clk_out(sel_buf[0]));
stdlib_clk_buf       u1_sel_buf (.clk_in(sel[1]), .clk_out(sel_buf[1]));
stdlib_clkmux2_gfree u0_glitch_free_mux2(.SE(SE), .test_mode(test_mode), .test_resetn(test_resetn), .rstn(rstn),.clk0(clk0),.clk1(clk1),.sel(sel_buf[0]),.clk_out(out_clk01));
stdlib_clkmux2_gfree u1_glitch_free_mux2(.SE(SE), .test_mode(test_mode), .test_resetn(test_resetn), .rstn(rstn),.clk0(out_clk01),.clk1(clk2),.sel(sel_buf[1]),.clk_out(out_clk));
endmodule
//==============================================
//1-3: 4 input mux with gfree clock select with or4 gate
module stdlib_clk_4mux1_or4(
  input     wire            SE          ,
  input     wire            test_mode   ,
  input     wire            test_resetn ,
  input     wire            clk0        ,
  input     wire            clk1        ,
  input     wire            clk2        ,
  input     wire            clk3        ,
  input     wire            rstn        ,
  input     wire    [ 1:0]  sel         ,
  output    wire            out_clk
);
stdlib_clkmux4_gfree u_stdlib_clkmux4_gfree(
  .clk0      (clk0   ), 
  .clk1      (clk1   ), 
  .clk2      (clk2   ), 
  .clk3      (clk3   ), 
  .SE        (SE     ),
  .test_mode (test_mode),
  .test_resetn(test_resetn),
  .rstn      (rstn   ), 
  .sel       (sel    ), 
  .clk_out   (out_clk));
endmodule
//==========================
module stdlib_clkmux4_gfree(
  input     wire            clk0        ,
  input     wire            clk1        ,
  input     wire            clk2        ,
  input     wire            clk3        ,
  input     wire            SE          ,
  input     wire            test_mode   ,
  input     wire            test_resetn ,
  input     wire            rstn        ,
  input     wire    [ 1:0]  sel         ,
  output    wire            clk_out
);
// ----------------------------
// Parameter Declaration
// ----------------------------
    parameter ULDY = 1 ;
// ----------------------------
// Wire Declaration
// ----------------------------
    wire        clk_out0        ;
    wire        clk_out1        ;
    wire        clk_out2        ;
    wire        clk_out3        ;
    wire        sel_clk0        ;
    wire        sel_clk1        ;
    wire        sel_clk2        ;
    wire        sel_clk3        ;
// -----------------------------
// Reg Declaration
// -----------------------------
    reg         sel_clk0_d0     ;
    reg         sel_clk0_d1     ;
    reg         sel_clk0_d2     ;
    reg         sel_clk1_d0     ;
    reg         sel_clk1_d1     ;
    reg         sel_clk1_d2     ;
    reg         sel_clk2_d0     ;
    reg         sel_clk2_d1     ;
    reg         sel_clk2_d2     ;
    reg         sel_clk3_d0     ;
    reg         sel_clk3_d1     ;
    reg         sel_clk3_d2     ;
// -----------------------------
//    Main Code Begin
// -----------------------------
    wire rstn_clk0, rstn_clk1, rstn_clk2, rstn_clk3;
    stdlib_rstn_sync  u0_rstn_sync (.rstn_in(rstn), .sync_clock(clk0), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk0));
    stdlib_rstn_sync  u1_rstn_sync (.rstn_in(rstn), .sync_clock(clk1), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk1));
    stdlib_rstn_sync  u2_rstn_sync (.rstn_in(rstn), .sync_clock(clk2), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk2));
    stdlib_rstn_sync  u3_rstn_sync (.rstn_in(rstn), .sync_clock(clk3), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk3));
    //assign rstn_clk0 = rstn;
    //assign rstn_clk1 = rstn;
    //assign rstn_clk2 = rstn;
    //assign rstn_clk3 = rstn;
    assign sel_clk0 =  (sel == 2'h0);
    assign sel_clk1 =  (sel == 2'h1);
    assign sel_clk2 =  (sel == 2'h2);
    assign sel_clk3 =  (sel == 2'h3);
// -----------------------------
//  clk0
// -----------------------------
    always @(posedge clk0 or negedge rstn_clk0)begin
        if(~rstn_clk0)begin
            sel_clk0_d0 <= #ULDY 1'b0;
            sel_clk0_d1 <= #ULDY 1'b0;
            sel_clk0_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk0_d0 <= #ULDY sel_clk0 & (~sel_clk1_d2) & (~sel_clk2_d2) & (~sel_clk3_d2);
            sel_clk0_d1 <= #ULDY sel_clk0_d0 ;
            sel_clk0_d2 <= #ULDY sel_clk0_d1 ;
        end
    end
// ----------------------------
//  clk1
// ----------------------------
    always @(posedge clk1 or negedge rstn_clk1)begin
        if(~rstn_clk1)begin
            sel_clk1_d0 <= #ULDY 1'b0;
            sel_clk1_d1 <= #ULDY 1'b0;
            sel_clk1_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk1_d0 <= #ULDY sel_clk1 & (~sel_clk0_d2) & (~sel_clk2_d2) & (~sel_clk3_d2);
            sel_clk1_d1 <= #ULDY sel_clk1_d0 ;
            sel_clk1_d2 <= #ULDY sel_clk1_d1 ;
        end
    end
// ---------------------------
//  clk2
// ---------------------------
    always @(posedge clk2 or negedge rstn_clk2)begin
        if(~rstn_clk2)begin
            sel_clk2_d0 <= #ULDY 1'b0;
            sel_clk2_d1 <= #ULDY 1'b0;
            sel_clk2_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk2_d0 <= #ULDY sel_clk2 & (~sel_clk0_d2) & (~sel_clk1_d2) & (~sel_clk3_d2);
            sel_clk2_d1 <= #ULDY sel_clk2_d0 ;
            sel_clk2_d2 <= #ULDY sel_clk2_d1 ;
        end
    end
// ---------------------------
//  clk3
// ---------------------------
    always @(posedge clk3 or negedge rstn_clk3)begin
        if(~rstn_clk3)begin
            sel_clk3_d0 <= #ULDY 1'b0;
            sel_clk3_d1 <= #ULDY 1'b0;
            sel_clk3_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk3_d0 <= #ULDY sel_clk3 & (~sel_clk0_d2) & (~sel_clk1_d2) & (~sel_clk2_d2);
            sel_clk3_d1 <= #ULDY sel_clk3_d0 ;
            sel_clk3_d2 <= #ULDY sel_clk3_d1 ;
        end
    end
    stdlib_clk_icg u_ckmux_icg0(.SE(SE),.clk_in(clk0),.en(sel_clk0_d1),.out_clk(clk_out0));
    stdlib_clk_icg u_ckmux_icg1(.SE(SE),.clk_in(clk1),.en(sel_clk1_d1),.out_clk(clk_out1));
    stdlib_clk_icg u_ckmux_icg2(.SE(SE),.clk_in(clk2),.en(sel_clk2_d1),.out_clk(clk_out2));
    stdlib_clk_icg u_ckmux_icg3(.SE(SE),.clk_in(clk3),.en(sel_clk3_d1),.out_clk(clk_out3));
    stdlib_clk_or4 u_clk_or2 (.clk0(clk_out0), .clk1(clk_out1), .clk2(clk_out2), .clk3(clk_out3), .clk_out(clk_out));
endmodule
//==============================================
//1-4: clock 4mux1 glitch free
module stdlib_clk_4mux1(
    input        SE  ,
    input        test_mode   ,
    input        test_resetn ,
    input        rstn,
    input        clk0,
    input        clk1,
    input        clk2,
    input        clk3,
    input [1:0]  sel ,
    output       out_clk
 );
wire [1:0]  sel_buf;
wire        out_clk01, out_clk23;
stdlib_clk_buf       u0_sel_buf (.clk_in(sel[0]), .clk_out(sel_buf[0]));
stdlib_clk_buf       u1_sel_buf (.clk_in(sel[1]), .clk_out(sel_buf[1]));
stdlib_clkmux2_gfree u0_glitch_free_mux2(.SE(SE), .test_mode(test_mode), .test_resetn(test_resetn), .rstn(rstn),.clk0(clk0), .clk1(clk1), .sel(sel_buf[0]),.clk_out(out_clk01));
stdlib_clkmux2_gfree u1_glitch_free_mux2(.SE(SE), .test_mode(test_mode), .test_resetn(test_resetn), .rstn(rstn),.clk0(clk2), .clk1(clk3), .sel(sel_buf[0]),.clk_out(out_clk23));
stdlib_clkmux2_gfree u2_glitch_free_mux2(.SE(SE), .test_mode(test_mode), .test_resetn(test_resetn), .rstn(rstn),.clk0(out_clk01),.clk1(out_clk23),.sel(sel_buf[1]),.clk_out(out_clk));
endmodule
//==============================================
//1-5: 6 input mux with gfree clock select
module stdlib_clk_6mux1(
  input     wire            SE          ,
  input     wire            test_mode   ,
  input     wire            test_resetn ,
  input     wire            clk0        ,
  input     wire            clk1        ,
  input     wire            clk2        ,
  input     wire            clk3        ,
  input     wire            clk4        ,
  input     wire            clk5        ,
  input     wire            rstn        ,
  input     wire    [ 2:0]  sel         ,
  output    wire            out_clk
);
stdlib_clkmux6_gfree u_stdlib_clkmux6_gfree(
  .clk0      (clk0   ), 
  .clk1      (clk1   ), 
  .clk2      (clk2   ), 
  .clk3      (clk3   ), 
  .clk4      (clk4   ), 
  .clk5      (clk5   ), 
  .SE        (SE     ),
  .test_mode (test_mode),
  .test_resetn(test_resetn),
  .rstn      (rstn   ), 
  .sel       (sel    ), 
  .clk_out   (out_clk)
);
endmodule
//=========================
module stdlib_clkmux6_gfree(
  input     wire            clk0        ,
  input     wire            clk1        ,
  input     wire            clk2        ,
  input     wire            clk3        ,
  input     wire            clk4        ,
  input     wire            clk5        ,
  input     wire            SE          ,
  input     wire            test_mode   ,
  input     wire            test_resetn ,
  input     wire            rstn        ,
  input     wire    [ 2:0]  sel         ,
  output    wire            clk_out
);
// --------------------------
// Parameter Declaration
// --------------------------
    parameter ULDY = 1 ;
// --------------------------
// Wire Declaration
// --------------------------
    wire        clk_out0        ;
    wire        clk_out1        ;
    wire        clk_out2        ;
    wire        clk_out3        ;
    wire        clk_out4        ;
    wire        clk_out5        ;
    wire        clk_out_or3_0   ;
    wire        clk_out_or3_1   ;
    wire        sel_clk0        ;
    wire        sel_clk1        ;
    wire        sel_clk2        ;
    wire        sel_clk3        ;
    wire        sel_clk4        ;
    wire        sel_clk5        ;
// --------------------------
// Reg Declaration
// --------------------------
    reg         sel_clk0_d0     ;
    reg         sel_clk0_d1     ;
    reg         sel_clk0_d2     ;
    reg         sel_clk1_d0     ;
    reg         sel_clk1_d1     ;
    reg         sel_clk1_d2     ;
    reg         sel_clk2_d0     ;
    reg         sel_clk2_d1     ;
    reg         sel_clk2_d2     ;
    reg         sel_clk3_d0     ;
    reg         sel_clk3_d1     ;
    reg         sel_clk3_d2     ;
    reg         sel_clk4_d0     ;
    reg         sel_clk4_d1     ;
    reg         sel_clk4_d2     ;
    reg         sel_clk5_d0     ;
    reg         sel_clk5_d1     ;
    reg         sel_clk5_d2     ;
// --------------------------
//   Main Code Begin
// --------------------------
    wire rstn_clk0, rstn_clk1, rstn_clk2, rstn_clk3, rstn_clk4, rstn_clk5;
    stdlib_rstn_sync  u0_rstn_sync (.rstn_in(rstn), .sync_clock(clk0), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk0));
    stdlib_rstn_sync  u1_rstn_sync (.rstn_in(rstn), .sync_clock(clk1), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk1));
    stdlib_rstn_sync  u2_rstn_sync (.rstn_in(rstn), .sync_clock(clk2), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk2));
    stdlib_rstn_sync  u3_rstn_sync (.rstn_in(rstn), .sync_clock(clk3), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk3));
    stdlib_rstn_sync  u4_rstn_sync (.rstn_in(rstn), .sync_clock(clk4), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk4));
    stdlib_rstn_sync  u5_rstn_sync (.rstn_in(rstn), .sync_clock(clk5), .test_mode(test_mode), .test_resetn(test_resetn), .rstn_out(rstn_clk5));
    //assign rstn_clk0 = rstn;
    //assign rstn_clk1 = rstn;
    //assign rstn_clk2 = rstn;
    //assign rstn_clk3 = rstn;
    //assign rstn_clk4 = rstn;
    //assign rstn_clk5 = rstn;
    assign sel_clk0 =  (sel == 3'h0);
    assign sel_clk1 =  (sel == 3'h1);
    assign sel_clk2 =  (sel == 3'h2);
    assign sel_clk3 =  (sel == 3'h3);
    assign sel_clk4 =  (sel == 3'h4);
    assign sel_clk5 =  (sel == 3'h5 || sel==3'h6 || sel==3'h7);
// --------------------------
//  clk0
// --------------------------
    always @(posedge clk0 or negedge rstn_clk0)begin
        if(~rstn_clk0)begin
            sel_clk0_d0 <= #ULDY 1'b0;
            sel_clk0_d1 <= #ULDY 1'b0;
            sel_clk0_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk0_d0 <= #ULDY sel_clk0 & (~sel_clk1_d2) & (~sel_clk2_d2) & (~sel_clk3_d2) & (~sel_clk4_d2) & (~sel_clk5_d2) ;
            sel_clk0_d1 <= #ULDY sel_clk0_d0 ;
            sel_clk0_d2 <= #ULDY sel_clk0_d1 ;
        end
    end
// ---------------------------
//  clk1
// ---------------------------
    always @(posedge clk1 or negedge rstn_clk1)begin
        if(~rstn_clk1)begin
            sel_clk1_d0 <= #ULDY 1'b0;
            sel_clk1_d1 <= #ULDY 1'b0;
            sel_clk1_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk1_d0 <= #ULDY sel_clk1 & (~sel_clk0_d2) & (~sel_clk2_d2) & (~sel_clk3_d2) & (~sel_clk4_d2) & (~sel_clk5_d2) ;
            sel_clk1_d1 <= #ULDY sel_clk1_d0 ;
            sel_clk1_d2 <= #ULDY sel_clk1_d1 ;
        end
    end
// ---------------------------
//  clk2
// ---------------------------
    always @(posedge clk2 or negedge rstn_clk2)begin
        if(~rstn_clk2)begin
            sel_clk2_d0 <= #ULDY 1'b0;
            sel_clk2_d1 <= #ULDY 1'b0;
            sel_clk2_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk2_d0 <= #ULDY sel_clk2 & (~sel_clk0_d2) & (~sel_clk1_d2) & (~sel_clk3_d2) & (~sel_clk4_d2) & (~sel_clk5_d2) ;
            sel_clk2_d1 <= #ULDY sel_clk2_d0 ;
            sel_clk2_d2 <= #ULDY sel_clk2_d1 ;
        end
    end
// ---------------------------
//  clk3
// ---------------------------
    always @(posedge clk3 or negedge rstn_clk3)begin
        if(~rstn_clk3)begin
            sel_clk3_d0 <= #ULDY 1'b0;
            sel_clk3_d1 <= #ULDY 1'b0;
            sel_clk3_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk3_d0 <= #ULDY sel_clk3 & (~sel_clk0_d0) & (~sel_clk1_d1) & (~sel_clk2_d2) & (~sel_clk4_d2) & (~sel_clk5_d2) ;
            sel_clk3_d1 <= #ULDY sel_clk3_d0 ;
            sel_clk3_d2 <= #ULDY sel_clk3_d1 ;
        end
    end
// ----------------------------
//  clk4
// ----------------------------
    always @(posedge clk4 or negedge rstn_clk4)begin
        if(~rstn_clk4)begin
            sel_clk4_d0 <= #ULDY 1'b0;
            sel_clk4_d1 <= #ULDY 1'b0;
            sel_clk4_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk4_d0 <= #ULDY sel_clk4 & (~sel_clk0_d2) & (~sel_clk1_d2) & (~sel_clk2_d2) & (~sel_clk3_d2) & (~sel_clk5_d2) ;
            sel_clk4_d1 <= #ULDY sel_clk4_d0 ;
            sel_clk4_d2 <= #ULDY sel_clk4_d1 ;
        end
    end
// ----------------------------
//  clk5
// ----------------------------
    always @(posedge clk5 or negedge rstn_clk5)begin
        if(~rstn_clk5)begin
            sel_clk5_d0 <= #ULDY 1'b0;
            sel_clk5_d1 <= #ULDY 1'b0;
            sel_clk5_d2 <= #ULDY 1'b0;
        end else begin
            sel_clk5_d0 <= #ULDY sel_clk5 & (~sel_clk0_d2) & (~sel_clk1_d2) & (~sel_clk2_d2) & (~sel_clk3_d2) & (~sel_clk4_d2) ;
            sel_clk5_d1 <= #ULDY sel_clk5_d0 ;
            sel_clk5_d2 <= #ULDY sel_clk5_d1 ;
        end
    end
    stdlib_clk_icg u_ckmux_icg0(.SE(SE),.clk_in(clk0),.en(sel_clk0_d1),.out_clk(clk_out0));
    stdlib_clk_icg u_ckmux_icg1(.SE(SE),.clk_in(clk1),.en(sel_clk1_d1),.out_clk(clk_out1));
    stdlib_clk_icg u_ckmux_icg2(.SE(SE),.clk_in(clk2),.en(sel_clk2_d1),.out_clk(clk_out2));
    stdlib_clk_icg u_ckmux_icg3(.SE(SE),.clk_in(clk3),.en(sel_clk3_d1),.out_clk(clk_out3));
    stdlib_clk_icg u_ckmux_icg4(.SE(SE),.clk_in(clk4),.en(sel_clk4_d1),.out_clk(clk_out4));
    stdlib_clk_icg u_ckmux_icg5(.SE(SE),.clk_in(clk5),.en(sel_clk5_d1),.out_clk(clk_out5));
    stdlib_clk_or3 u0_clk_or3 (.clk0(clk_out0), .clk1(clk_out1), .clk2(clk_out2), .clk_out(clk_out_or3_0)); 
    stdlib_clk_or3 u1_clk_or3 (.clk0(clk_out3), .clk1(clk_out4), .clk2(clk_out5), .clk_out(clk_out_or3_1)); 
    stdlib_clk_or  u0_clk_or2 (.clk0(clk_out_or3_0), .clk1(clk_out_or3_1), .clk_out(clk_out));
endmodule
//==============================================
//1-6: clock 90degree shift
module stdlib_clk_shift90 (
   input       SE  ,
   input       rstn,
   input       clk0,
   input       clk1,
   input       sel ,
   output  reg out_clk
);
always@(posedge clk0) begin
  out_clk <= clk1;
end
endmodule
//==============================================
//2-0: div2 fixed without en
module stdlib_clk_div2    #(parameter DIV_WIDTH=2)
(
    input SE,
    input rstn,
    input clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output reg out_clk
);
wire       rstn_clkin;
assign     rstn_clkin = rstn;
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
       out_clk `__EQ_BLK_NOBLK__ 1'b0;
    else 
       out_clk `__EQ_BLK_NOBLK__ ~out_clk;
end
endmodule
//==============================================
//2-1: div2 fixed with en
module stdlib_clk_div2_en  #(parameter DIV_WIDTH=4)
(
    input SE,
    input rstn,
    input clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output reg out_clk_en,
    output reg out_clk
);
wire    rstn_clkin;
//stdlib_rstn_sync  u_div2en_rstn_sync (.rstn_in(rstn), .sync_clock(clk_in), .rstn_out(rstn_clkin));
assign  rstn_clkin = rstn;
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
      out_clk_en <= 1'b0;
    else 
      out_clk_en <= #0.1 ~out_clk_en;
end
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
       out_clk `__EQ_BLK_NOBLK__ 1'b0;
    else 
       out_clk `__EQ_BLK_NOBLK__ ~out_clk;
end
endmodule
//==============================================
//2-2: div3 fixed without en
module stdlib_clk_div3   #(parameter DIV_WIDTH=4)
(
    input SE,
    input rstn,
    input clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output out_clk
);
reg [1:0] cnt_h;
reg [1:0] cnt_l;
reg       clk_out_p ,clk_out_n; 
wire    rstn_clkin;
//stdlib_rstn_sync  u_div3_rstn_sync (.rstn_in(rstn), .sync_clock(clk_in), .rstn_out(rstn_clkin));
assign  rstn_clkin = rstn;
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
        cnt_h <= 2'd0;
    else if(cnt_h>=2'd2) 
        cnt_h <= 2'd0;
    else
        cnt_h <= cnt_h + 1'b1;
end 
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
        clk_out_p `__EQ_BLK_NOBLK__ 1'b0;
    else if(cnt_h==2'd0) 
        clk_out_p `__EQ_BLK_NOBLK__ ~clk_out_p;
end 
always@(negedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) begin
        cnt_l     <= 2'd0;
        clk_out_n `__EQ_BLK_NOBLK__ 1'b0;
    end else begin
      if(cnt_l >=2'd2) begin
        cnt_l <= 2'd0;
        clk_out_n `__EQ_BLK_NOBLK__ ~clk_out_n;
      end else begin
        cnt_l <= cnt_l + 1'b1;
      end
    end
end 
stdlib_clk_xor2  u_clk_xor(.clk0(clk_out_p), .clk1(clk_out_n), .out_clk(out_clk));
endmodule
//==============================================
//2-3: div5 fixed without en
module stdlib_clk_div5   #(parameter DIV_WIDTH=4)
(
    input SE,
    input rstn,
    input clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output out_clk
);
reg [2:0] cnt_h;
reg [2:0] cnt_l;
reg       clk_out_p ,clk_out_n; 
//===========================
wire    rstn_clkin;
//stdlib_rstn_sync  u_div5_rstn_sync (.rstn_in(rstn), .sync_clock(clk_in), .rstn_out(rstn_clkin));
assign  rstn_clkin = rstn;
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
        cnt_h <= 3'd0;
    else if(cnt_h>=3'd4) 
        cnt_h <= 3'd0;
    else
        cnt_h <= cnt_h + 1'b1;
end 
always@(posedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) 
        clk_out_p `__EQ_BLK_NOBLK__ 1'b0;
    else if(cnt_h==3'd0) 
        clk_out_p `__EQ_BLK_NOBLK__ ~clk_out_p;
end 
always@(negedge clk_in or negedge rstn_clkin) begin
    if(!rstn_clkin) begin
        cnt_l     <= 3'd0;
        clk_out_n `__EQ_BLK_NOBLK__ 1'b0;
    end else begin
      if(cnt_l >=3'd4) begin
        cnt_l <= 3'd0;
        clk_out_n `__EQ_BLK_NOBLK__ ~clk_out_n;
      end else begin
        cnt_l <= cnt_l + 1'b1;
      end
    end
end 
stdlib_clk_xor2  u_clk_xor(.clk0(clk_out_p), .clk1(clk_out_n), .out_clk(out_clk));
endmodule
//==============================================
//2-4: div10 fixed without en
module stdlib_clk_div10   #(parameter DIV_WIDTH=4)
(
    input                 SE,
    input                 rstn,
    input                 clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output                out_clk
);
reg       clk_in_div10;
reg [2:0] counter;
//=============================
wire       rstn_clkin;
//stdlib_rstn_sync  u_div10_rstn_sync (.rstn_in(rstn), .sync_clock(clk_in), .rstn_out(rstn_clkin));
assign  rstn_clkin = rstn;
always@(posedge clk_in or negedge rstn_clkin)begin
    if(!rstn_clkin) begin
        counter      <= 3'd0;
        clk_in_div10 `__EQ_BLK_NOBLK__ 1'b0;
    end else if(counter >= 3'd4)begin
        counter      <= 3'd0;
        clk_in_div10 `__EQ_BLK_NOBLK__ ~clk_in_div10;
    end else begin
        counter <= counter+1'b1;
    end
end
assign   out_clk = clk_in_div10;
endmodule
//==============================================
//2-5: div with even divisor
module stdlib_clk_div_even #(parameter DIV_WIDTH=4)
(
    input                 SE,
    input                 rstn,
    input                 clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output                out_clk
);
reg   [DIV_WIDTH-2:0]  counter;
reg                    clkin_div_even;
wire  [DIV_WIDTH-2:0]  div_half;
//=============================
wire    rstn_clkin;
assign  rstn_clkin = rstn;
assign  div_half = (divisor==0 || divisor==1) ? 0 : divisor[DIV_WIDTH-1:1] - 1;
always@(posedge clk_in or negedge rstn_clkin)begin
   if(!rstn_clkin) begin
     counter <= {(DIV_WIDTH-1){1'b0}};
     clkin_div_even `__EQ_BLK_NOBLK__ 1'b0;
   end else if(counter >= div_half) begin
     counter <= {(DIV_WIDTH-1){1'b0}};
     clkin_div_even `__EQ_BLK_NOBLK__ ~clkin_div_even;
   end else begin
     counter <= counter + 1'b1;
   end
end
assign  out_clk = clkin_div_even;
endmodule
//==============================================
//2-6: clock div with divisor config without en
module stdlib_clk_divcfg    #(parameter DIV_WIDTH=4)
(
    input                 SE,
    input                 rstn,
    input                 clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output                out_clk
);
reg                 fout     ;
reg                 clk_out_p; 
reg                 clk_out_n;
reg [DIV_WIDTH-1:0] counter  ;
reg [DIV_WIDTH-1:0] cnt_p    ;
reg [DIV_WIDTH-1:0] cnt_n    ;
reg rstn_d0 ;
reg rstn_d1 ;
reg rstn_d2 ;
//===========================
always@(posedge clk_in) begin
    rstn_d0 <= rstn;
end
//sync the rstn to the clk domain
always @(posedge clk_in or negedge rstn) begin
   if(~rstn)
     rstn_d1 <= 1'b0;
   else
     rstn_d1 <= rstn_d0;
end
//only odd number to turn on the rstn_d2 for the duty cycle adjustment 
always @(posedge clk_in or negedge rstn) begin
   if(~rstn)
    rstn_d2 <= 1'b0;
   else
    rstn_d2 <=rstn_d1 & divisor[0];
end
//assign the number to counter low and high
//for example: for divided by 5, cnt_n=2, cnt_p=1
//             for divided by 9, cnt_n=4, cnt_p=3
//             for divided by 8  cnt_n=3, cnt_p=3
always @(posedge clk_in) begin
  cnt_p <= (divisor[DIV_WIDTH-1:1] - 1);
  cnt_n <=  divisor[0] ? divisor[DIV_WIDTH-1:1] : cnt_p;
end
assign rstn_d1_dft = SE ? rstn : rstn_d1;
always @(posedge clk_in or negedge rstn_d1_dft) begin
     if(~rstn_d1_dft) begin
       fout<=1'b0;
       counter<=1'b0;
       clk_out_p `__EQ_BLK_NOBLK__ 1'b0;
     end
     else begin 
       clk_out_p `__EQ_BLK_NOBLK__ fout;
       if(fout == 1'b0 && counter >= cnt_n || fout==1 && counter >= cnt_p) begin
         fout<=~fout;
         counter<=1'b0;
       end
       else begin       
         counter <=counter+1;
       end
     end
end
assign rstn_d2_dft = SE ? rstn : rstn_d2;
//use negative edge to adjust the duty cycle if it divides by odd number
//shift clk_out_p by half clk cycle
always @(negedge clk_in or negedge rstn_d2_dft) begin
   if (~rstn_d2_dft) clk_out_n `__EQ_BLK_NOBLK__ 1'b0;
   else clk_out_n `__EQ_BLK_NOBLK__ clk_out_p;
end
wire out_clk_div;
wire div01_bypass = (divisor==1 || divisor==0);
//assign out_clk_div = ~(~clk_out_n & ~clk_out_p);
//stdlib_clk_inv   u0_clk_inv (.clk_in(clk_out_n), .clk_inv_out(clk_out_n_inv));
//stdlib_clk_inv   u1_clk_inv (.clk_in(clk_out_p), .clk_inv_out(clk_out_p_inv));
//stdlib_clk_nand  u0_clk_nand(.clk0(clk_out_n_inv), .clk1(clk_out_p_inv), .clk_out(out_clk_div));
stdlib_clk_or    u0_clk_or2 (.clk0(clk_out_p), .clk1(clk_out_n), .clk_out(out_clk_div));
stdlib_clk_buf   u0_sel_buf (.clk_in(div01_bypass),.clk_out(sel_buf));
stdlib_clk_2mux1_nor  u0_stdlib_clk_2mux1_nor(.SE(SE),.rstn(rstn_d1_dft),.test_mode(1'b0), .test_resetn(1'b1), .clk0(out_clk_div), .clk1(clk_in), .sel(sel_buf),.out_clk(out_clk));
endmodule
//==============================================
//2-7: clock divcfg with en
module stdlib_clk_divcfg_en
  #(parameter DIV_WIDTH=4)
    (
    input                 SE,
    input                 rstn,
    input                 clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output                out_clk,
    output                out_clk_en
   );
reg                 fout     ;
reg                 clk_out_p; 
reg                 clk_out_n;
reg [DIV_WIDTH-1:0] counter  ;
reg [DIV_WIDTH-1:0] cnt_p    ;
reg [DIV_WIDTH-1:0] cnt_n    ;
reg clk_div_en_r; //Billy, 2019-11-6
reg rstn_d0 ;
reg rstn_d1 ;
reg rstn_d2 ;
//======================
always@(posedge clk_in) begin
    rstn_d0 <= rstn;
end
//sync the rstn to the clk domain
always @(posedge clk_in or negedge rstn) begin
   if(~rstn) begin
     rstn_d1 <=  1'b0;
   end else begin
     rstn_d1 <= rstn_d0;
   end
end
//only odd number to turn on the rstn_d2 for the duty cycle adjustment 
always @(posedge clk_in or negedge rstn) begin
   if(~rstn)
    rstn_d2 <= 1'b0;
   else
    rstn_d2 <=rstn_d1 & divisor[0];
end
//assign the number to counter low and high
//for example: for divided by 5, cnt_n=2, cnt_p=1
//             for divided by 9, cnt_n=4, cnt_p=3
//             for divided by 8  cnt_n=3, cnt_p=3
always @(posedge clk_in) begin
  cnt_p <= (divisor[DIV_WIDTH-1:1] - 1);
  cnt_n <=  divisor[0] ? divisor[DIV_WIDTH-1:1] : cnt_p;
end
assign rstn_d1_dft = SE ? rstn : rstn_d1;
always @(posedge clk_in or negedge rstn_d1_dft) begin
     if(~rstn_d1_dft) begin
       fout <= 1'b0;
       counter <= 1'b0;
       clk_out_p `__EQ_BLK_NOBLK__ 1'b0;
     end
     else begin 
       clk_out_p `__EQ_BLK_NOBLK__ fout;
       if(fout == 1'b0 && counter >= cnt_n || fout==1 && counter >= cnt_p) begin
         fout <= ~fout;
         counter <= 1'b0;
       end
       else begin       
         counter <= counter+1;
       end
     end
end
//Billy, 2019-11-06
always @(posedge clk_in or negedge rstn_d1_dft) begin
     if(~rstn_d1_dft) 
       clk_div_en_r <= 1'b0;
     else if(fout == 1'b0 && counter >= cnt_n)
       clk_div_en_r <= 1'b1;
     else
       clk_div_en_r <= 1'b0;
end
//End by Billy
assign rstn_d2_dft = SE ? rstn : rstn_d2;
//use negative edge to adjust the duty cycle if it divides by odd number
//shift clk_out_p by half clk cycle
always @(negedge clk_in or negedge rstn_d2_dft) begin
   if (~rstn_d2_dft) clk_out_n `__EQ_BLK_NOBLK__ 1'b0;
   else clk_out_n `__EQ_BLK_NOBLK__ clk_out_p;
end
wire div01_bypass = (divisor==1 || divisor==0);
//wire out_clk_div = ~(~clk_out_n & ~clk_out_p);
//stdlib_clk_inv   u0_clk_inv (.clk_in(clk_out_n), .clk_inv_out(clk_out_n_inv));
//stdlib_clk_inv   u1_clk_inv (.clk_in(clk_out_p), .clk_inv_out(clk_out_p_inv));
//stdlib_clk_nand  u0_clk_nand(.clk0(clk_out_n_inv), .clk1(clk_out_p_inv), .clk_out(out_clk_div));
stdlib_clk_or    u0_clk_or2 (.clk0(clk_out_p), .clk1(clk_out_n), .clk_out(out_clk_div));
stdlib_clk_buf   u0_sel_buf (.clk_in(div01_bypass),.clk_out(sel_buf));
stdlib_clk_2mux1_nor  u0_stdlib_clk_2mux1_nor(.SE(SE),.rstn(rstn_d1_dft),.test_mode(1'b0), .test_resetn(1'b1), .clk0(out_clk_div), .clk1(clk_in), .sel(sel_buf),.out_clk(out_clk));
assign out_clk_en = div01_bypass ? 1'b1 : clk_div_en_r; //out_clk_div; //Billy, 2019-11-6
endmodule
//==============================================
//2-8: clock fraction divider
module stdlib_clk_fracdiv  #(parameter DIV_WIDTH=17)
(
    input                 SE,
    input                 rstn,
    input                 clk_in,
    input [DIV_WIDTH-1:0] divisor,
    output                out_clk
);
stdlib_frac_div u_frac_div(
       .te       (SE             )
      ,.rst_n    (rstn           )
      ,.fin      (clk_in         )
      ,.soft_rst (divisor[16]    )
      ,.div_num  (divisor[15:8]  )
      ,.div_main (divisor[7:0]   )
      ,.fout     (out_clk        )
    );
endmodule
//==========================
module stdlib_frac_div
(
    te,
    fin,
    rst_n,
    soft_rst,
    div_main,    //the divider N for dual modulus N/N+1 divider;
    div_num,    //the numerator M for the fractional divider
    fout
);
parameter    N_WIDTH = 8;
parameter    M_WIDTH = 8;
input                     te;    //test mode enable
input                     fin;
input                     rst_n;
input                     soft_rst;
input    [N_WIDTH-1:0]    div_main;
input    [M_WIDTH-1:0]    div_num;
output                    fout;
//=================================
reg                       fout_q;
reg    [N_WIDTH-1:0]      div_cnt;    //the divider counter
reg    [M_WIDTH-1:0]      frac_accu;    //fractional divider accumulator
reg                       frac_accu_ov;
wire                      div_cnt_clr;
wire    [M_WIDTH:0]       frac_sum;
wire                      rstn_fin;
//=================================
assign        div_cnt_clr = frac_accu_ov ? (div_cnt==div_main) : (div_cnt == (div_main - 1'b1));
assign        frac_sum    = frac_accu + div_num;
//stdlib_rstn_sync  u_fracdiv_rstn_sync (.rstn_in(rst_n), .sync_clock(fin), .rstn_out(rstn_fin));
assign  rstn_fin = rst_n;
always @(posedge fin or negedge rstn_fin)
begin
  if(~rstn_fin) 
    div_cnt <= {(N_WIDTH){1'b0}};
  else if (soft_rst == 1'b1) 
    div_cnt <= {(N_WIDTH){1'b0}};
  else if (div_cnt_clr) 
    div_cnt <= {(N_WIDTH){1'b0}};
  else 
    div_cnt <= div_cnt + 1'b1;
end
always @(posedge fin or negedge rstn_fin)
begin
  if(~rstn_fin) 
    fout_q <= 1'b0;
  else 
    fout_q <= div_cnt_clr;
end
always @(posedge fin or negedge rstn_fin)
begin
  if(~rstn_fin) begin
    frac_accu    <= {(M_WIDTH){1'b0}};
    frac_accu_ov <= 1'b0;
  end else if(soft_rst == 1'b1) begin
    frac_accu    <= {(M_WIDTH){1'b0}};
    frac_accu_ov <= 1'b0;
  end else if(div_cnt_clr == 1'b1) begin
    frac_accu    <= frac_sum[M_WIDTH-1:0];
    frac_accu_ov <= frac_sum[M_WIDTH];
  end
end
assign    fout = te ? fin : fout_q;
endmodule
//==============================================
//3-0: delay chain, 32x340ps=10ns
module stdlib_dly_chain  #(parameter SEL_WIDTH=5)
(
   input                    dly_in
  ,output                   dly_out
  ,input   [SEL_WIDTH-1:0]  dly_sel
);
wire  [31:0]   dly_stage;
wire  [7:0]    mux_out;
wire  [1:0]    mux_2_out;
stdlib_dly200p_cell dly_stage_01 (.dly_out(dly_stage[ 1]), .dly_in(dly_in       ));
stdlib_dly200p_cell dly_stage_02 (.dly_out(dly_stage[ 2]), .dly_in(dly_stage[ 1]));
stdlib_dly200p_cell dly_stage_03 (.dly_out(dly_stage[ 3]), .dly_in(dly_stage[ 2]));
stdlib_dly200p_cell dly_stage_04 (.dly_out(dly_stage[ 4]), .dly_in(dly_stage[ 3]));
stdlib_dly200p_cell dly_stage_05 (.dly_out(dly_stage[ 5]), .dly_in(dly_stage[ 4]));
stdlib_dly200p_cell dly_stage_06 (.dly_out(dly_stage[ 6]), .dly_in(dly_stage[ 5]));
stdlib_dly200p_cell dly_stage_07 (.dly_out(dly_stage[ 7]), .dly_in(dly_stage[ 6]));
stdlib_dly200p_cell dly_stage_08 (.dly_out(dly_stage[ 8]), .dly_in(dly_stage[ 7]));
stdlib_dly200p_cell dly_stage_09 (.dly_out(dly_stage[ 9]), .dly_in(dly_stage[ 8]));
stdlib_dly200p_cell dly_stage_10 (.dly_out(dly_stage[10]), .dly_in(dly_stage[ 9]));
stdlib_dly200p_cell dly_stage_11 (.dly_out(dly_stage[11]), .dly_in(dly_stage[10]));
stdlib_dly200p_cell dly_stage_12 (.dly_out(dly_stage[12]), .dly_in(dly_stage[11]));
stdlib_dly200p_cell dly_stage_13 (.dly_out(dly_stage[13]), .dly_in(dly_stage[12]));
stdlib_dly200p_cell dly_stage_14 (.dly_out(dly_stage[14]), .dly_in(dly_stage[13]));
stdlib_dly200p_cell dly_stage_15 (.dly_out(dly_stage[15]), .dly_in(dly_stage[14]));
stdlib_dly200p_cell dly_stage_16 (.dly_out(dly_stage[16]), .dly_in(dly_stage[15]));
stdlib_dly200p_cell dly_stage_17 (.dly_out(dly_stage[17]), .dly_in(dly_stage[16]));
stdlib_dly200p_cell dly_stage_18 (.dly_out(dly_stage[18]), .dly_in(dly_stage[17]));
stdlib_dly200p_cell dly_stage_19 (.dly_out(dly_stage[19]), .dly_in(dly_stage[18]));
stdlib_dly200p_cell dly_stage_20 (.dly_out(dly_stage[20]), .dly_in(dly_stage[19]));
stdlib_dly200p_cell dly_stage_21 (.dly_out(dly_stage[21]), .dly_in(dly_stage[20]));
stdlib_dly200p_cell dly_stage_22 (.dly_out(dly_stage[22]), .dly_in(dly_stage[21]));
stdlib_dly200p_cell dly_stage_23 (.dly_out(dly_stage[23]), .dly_in(dly_stage[22]));
stdlib_dly200p_cell dly_stage_24 (.dly_out(dly_stage[24]), .dly_in(dly_stage[23]));
stdlib_dly200p_cell dly_stage_25 (.dly_out(dly_stage[25]), .dly_in(dly_stage[24]));
stdlib_dly200p_cell dly_stage_26 (.dly_out(dly_stage[26]), .dly_in(dly_stage[25]));
stdlib_dly200p_cell dly_stage_27 (.dly_out(dly_stage[27]), .dly_in(dly_stage[26]));
stdlib_dly200p_cell dly_stage_28 (.dly_out(dly_stage[28]), .dly_in(dly_stage[27]));
stdlib_dly200p_cell dly_stage_29 (.dly_out(dly_stage[29]), .dly_in(dly_stage[28]));
stdlib_dly200p_cell dly_stage_30 (.dly_out(dly_stage[30]), .dly_in(dly_stage[29]));
stdlib_dly200p_cell dly_stage_31 (.dly_out(dly_stage[31]), .dly_in(dly_stage[30]));
stdlib_dly_chain_mux4 dly_chain_mux0
(
    .I0  (dly_in      ),
	.I1  (dly_stage[1]),
	.I2  (dly_stage[2]),
	.I3  (dly_stage[3]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[0]  )
);
stdlib_dly_chain_mux4 dly_chain_mux1
(
    .I0  (dly_stage[4]),
	.I1  (dly_stage[5]),
	.I2  (dly_stage[6]),
	.I3  (dly_stage[7]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[1]  )
);
stdlib_dly_chain_mux4 dly_chain_mux2
(
    .I0  (dly_stage[8]),
	.I1  (dly_stage[9]),
	.I2  (dly_stage[10]),
	.I3  (dly_stage[11]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[2]  )
);
stdlib_dly_chain_mux4 dly_chain_mux3
(
    .I0  (dly_stage[12]),
	.I1  (dly_stage[13]),
	.I2  (dly_stage[14]),
	.I3  (dly_stage[15]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[3]  )
);
stdlib_dly_chain_mux4 dly_chain_mux4
(
    .I0  (dly_stage[16]),
	.I1  (dly_stage[17]),
	.I2  (dly_stage[18]),
	.I3  (dly_stage[19]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[4]  )
);
stdlib_dly_chain_mux4 dly_chain_mux5
(
    .I0  (dly_stage[20]),
	.I1  (dly_stage[21]),
	.I2  (dly_stage[22]),
	.I3  (dly_stage[23]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[5]  )
);
stdlib_dly_chain_mux4 dly_chain_mux6
(
    .I0  (dly_stage[24]),
	.I1  (dly_stage[25]),
	.I2  (dly_stage[26]),
	.I3  (dly_stage[27]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[6]  )
);
stdlib_dly_chain_mux4 dly_chain_mux7
(
    .I0  (dly_stage[28]),
	.I1  (dly_stage[29]),
	.I2  (dly_stage[30]),
	.I3  (dly_stage[31]),
	.sel (dly_sel[1:0]),
	.Z   (mux_out[7]  )
);
stdlib_dly_chain_mux4 dly_chain_mux8
(
    .I0  (mux_out[0]),
	.I1  (mux_out[1]),
	.I2  (mux_out[2]),
	.I3  (mux_out[3]),
	.sel (dly_sel[3:2]),
	.Z   (mux_2_out[0])
);
stdlib_dly_chain_mux4 dly_chain_mux9
(
    .I0  (mux_out[4]),
	.I1  (mux_out[5]),
	.I2  (mux_out[6]),
	.I3  (mux_out[7]),
	.sel (dly_sel[3:2]),
	.Z   (mux_2_out[1])
);
stdlib_dly_chain_mux2 dly_chain_mux10 (
   .I0 (mux_2_out[0]), 
   .I1 (mux_2_out[1]), 
   .sel(dly_sel[4]  ),
   .Z  (dly_out     ));
endmodule
//=================================================
//4-0: clock test mux with scan enable
module stdlib_test_clk_mux
(
   input  func_clk
  ,input  slow_clk
  ,input  sel_slow 
  ,output out_clk
);
stdlib_clk_mux u_testclk_mux (.clk0(func_clk), .clk1(slow_clk), .sel(sel_slow), .out_clk(out_clk));
endmodule
//=================================================
//4-1: RESET test mux with test_mode
module stdlib_test_reset_mux(
     input test_mode
    ,input rstn_in
    ,input test_resetn
    ,output rstn_out
);
//assign rstn_out = test_mode ? test_resetn: rstn_in;
stdlib_clk_mux u_testreset_mux (.clk0(rstn_in), .clk1(test_resetn), .sel(test_mode), .out_clk(rstn_out));
endmodule
//=================================================
//4-2: OCC
module stdlib_test_occ_ctrl
(
    input      fast_clk          //i, func clock
   ,input      slow_clk          //i, scan clock
   ,input      scan_en           //i, connect to crg_top
   ,input      test_mode         //i, connect to crg_top
   ,input      fast_capture_mode //i, tie 0 in rtl 
   ,output     out_clk           //o, clock output to IP
   ,input      scan_in           //i, tie 0 in rtl
   ,output     scan_out          //o, NC in rtl
);
wire  clk_fast_buf, clk_slow_buf, scan_en_buf, test_mode_buf, fastcap_mode_buf, scan_in_buf;
wire  scan_out_int, fast_clock_en, slow_clock_en, clock_mux_select;
wire  clk_fast_gated, clk_slow_gated;
stdlib_clk_buf  u0_fast_ckbuf   (.clk_in(fast_clk),       .clk_out(clk_fast_buf));
stdlib_clk_buf  u0_slow_ckbuf   (.clk_in(slow_clk),       .clk_out(clk_slow_buf));
stdlib_buf      u0_scanen_buf   (.din(scan_en),           .z_out(scan_en_buf));
stdlib_buf      u0_testmode_buf (.din(test_mode),         .z_out(test_mode_buf));
stdlib_buf      u0_fastcap_buf  (.din(fast_capture_mode), .z_out(fastcap_mode_buf));
stdlib_buf      u0_scanin_buf   (.din(scan_in),           .z_out(scan_in_buf));
stdlib_buf      u0_scanout_buf  (.din(scan_out_int),      .z_out(scan_out));
stdlib_occ_ctrl    u0_test_occ_ctrl
(
     .fast_clock            ( clk_fast_buf    ),
     .slow_clock            ( clk_slow_buf    ),
     .bypass_clock          ( out_clk         ),
     .scan_en               ( scan_en_buf     ),
     .test_mode             ( test_mode_buf   ),
     .fast_capture_mode     ( fastcap_mode_buf),
     .scan_in               ( scan_in_buf     ),
     .scan_out              ( scan_out_int    ),
     .fast_clock_en         ( fast_clock_en   ),
     .slow_clock_en         ( slow_clock_en   ),
     .clock_mux_select      ( clock_mux_select)
);
stdlib_clk_icg u0_fast_clk_cgc(.SE(fast_clock_en), .clk_in(clk_fast_buf), .en(fast_clock_en), .out_clk(clk_fast_gated));
stdlib_clk_icg u0_scan_clk_cgc(.SE(slow_clock_en), .clk_in(clk_slow_buf), .en(slow_clock_en), .out_clk(clk_slow_gated));
stdlib_clk_mux u0_outclk_mux  (.clk0(clk_fast_gated), .clk1(clk_slow_gated), .sel(clock_mux_select), .out_clk(out_clk));
endmodule
module stdlib_occ_ctrl
(
    input        fast_clock
   ,input        slow_clock
   ,input        bypass_clock
   ,input        scan_en
   ,input        test_mode
   ,input        fast_capture_mode
   ,input        scan_in
   ,output reg   scan_out
   ,output       fast_clock_en
   ,output       slow_clock_en
   ,output       clock_mux_select
);
reg      SE_SLOW_CLK;
reg      BYPASS_SHIFT_FF;
wire     SCAN_EN_inv_sync;
wire     SHIFT_REG_CLK_en;
wire     ShiftReg_EN;
wire     SHIFT_REG_CLK, SHIFT_REG_CLK_G;
wire     sel_slow;
wire     SCAN_OUT_d;
wire     ShiftReg_SCAN_OUT;
//sync the scan_en to fast clock
always @(negedge slow_clock) begin
    SE_SLOW_CLK <= scan_en;
end
stdlib_occ_sync_init0 u_scanen_sync(.clk(fast_clock), .cdn(~scan_en), .din(~SE_SLOW_CLK), .qout(SCAN_EN_inv_sync));
//open the fast clock(func clock) while scan_en low
assign  SHIFT_REG_CLK_en = test_mode & ShiftReg_EN & SCAN_EN_inv_sync;
stdlib_clk_icg  u0_fast_clkicg  (.SE(SHIFT_REG_CLK_en), .clk_in(fast_clock), .en(SHIFT_REG_CLK_en), .out_clk(SHIFT_REG_CLK_G));
//sel the slow clock while scanen and not in fast capture mode
//sel the fast clock while not slow
assign  sel_slow = scan_en | (~fast_capture_mode);
stdlib_clk_mux  u0_shiftclk_mux (.clk0(SHIFT_REG_CLK_G),.clk1(slow_clock), .sel(sel_slow), .out_clk(SHIFT_REG_CLK));
always @(posedge bypass_clock) begin
    BYPASS_SHIFT_FF <= scan_in & scan_en;
end
assign  SCAN_OUT_d = (!test_mode) ? BYPASS_SHIFT_FF : ShiftReg_SCAN_OUT;
always @ (negedge bypass_clock) begin
    scan_out <= SCAN_OUT_d & scan_en;
end
//1. shift the scan in for 8 cycles to out
//2. open the fast clock while scan_en change to low within 8 cycles
stdlib_occ_shift_reg u0_ShiftReg 
(
   .clk             ( SHIFT_REG_CLK    ),
   .scan_en         ( scan_en          ),
   .scan_in         ( scan_in          ),
   .scan_out        ( ShiftReg_SCAN_OUT),
   .some_ones_left  ( ShiftReg_EN      )
);
//while in capture mode, scan_en low, and scan_in shift out finished;
//or not in testmode (using func clock), sel the fast clock
//else gating it, it not output to scan chain.
assign fast_clock_en    = (ShiftReg_SCAN_OUT & fast_capture_mode & SCAN_EN_inv_sync) | ~test_mode;
//while scan shift, sel the slow clock(scan clock), else gating it.
assign slow_clock_en    = ((ShiftReg_SCAN_OUT | scan_en) & test_mode);
//sel slow clock while scan_en and not-capture status
assign clock_mux_select = ((scan_en | ~fast_capture_mode) & test_mode);
endmodule
module stdlib_occ_shift_reg
(
   input    clk,
   input    scan_en,
   input    scan_in,
   output   scan_out,
   output   some_ones_left
);
wire        scan_in_gated;
reg  [7:0]  scan_FF;
//shift scan_in 8cycles while scan mode
assign  scan_in_gated = scan_in & scan_en;
always @(posedge clk) begin
    scan_FF <= {scan_in_gated, scan_FF[7:1]};
end
assign  some_ones_left = |scan_FF;
assign  scan_out = scan_FF[0];
endmodule
module stdlib_occ_sync_init0
(
    input  clk,
    input  cdn,
    input  din,
    output  reg qout
);
reg   ntc_retiming_q_reg;
always @(posedge clk or negedge cdn) begin
    if(!cdn) begin
        ntc_retiming_q_reg <= 1'b0;
        qout <= 1'b0;
    end else begin
        ntc_retiming_q_reg <= din;
        qout <= ntc_retiming_q_reg;
    end
end
endmodule
//=================================================
//4-3: test mux for fast clock, func clock and scan clock
module stdlib_clk_occmux 
(
     input sel_fast
    ,input sel_slow
    ,input clk_fast
    ,input clk_slow
    ,input clk_func
    ,output out_clk
);
wire    clk_func_slow;
stdlib_clk_mux u0_func_mux (.clk0(clk_func),      .clk1(clk_slow), .sel(sel_slow), .out_clk(clk_func_slow));
stdlib_clk_mux u0_fast_mux (.clk0(clk_func_slow), .clk1(clk_fast), .sel(sel_fast), .out_clk(out_clk));
endmodule
//=================================================
//4-4: parameter test mux for OCC
module  stdlib_test_occparam_mux  #(parameter  DATA_WIDTH=2)
(
    input                     sel_fast,
    input   [DATA_WIDTH-1:0]  func_data,
    input   [DATA_WIDTH-1:0]  fast_data,
    output  [DATA_WIDTH-1:0]  out_data
);
assign  out_data = sel_fast ? fast_data : func_data;
endmodule
//===================The End=======================
